package com.mobile.collect.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.mobile.collect.R;
import com.mobile.collect.beans.DevicePointInfo;
import com.mobile.collect.db.EntityManager;

import java.util.ArrayList;
import java.util.List;

import cn.droidlover.xdroidmvp.kit.Kits;
import cn.droidlover.xdroidmvp.kit.NLog;

public class ImageLayout extends FrameLayout implements View.OnClickListener {

    List<DevicePointInfo> points;
    List<DevicePointInfo> selectList = new ArrayList<>();

    FrameLayout layouPoints;

    private ZoomImageView imgBg;
    private float iX, iY, iScale = 1;

    private boolean isMultipleModel = false;//是否为多选
    Context mContext;
    ImageLayout.ImageLayoutListener listener;
    ImageLayout.OnLayoutSuccessListener onLayoutSuccessListener;

    public ImageLayout(Context context) {
        this(context, null);
    }

    public ImageLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ImageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }


    private void initView(Context context, AttributeSet attrs) {

        mContext = context;
        points = new ArrayList<>();
        View imgPointLayout = inflate(context, R.layout.layout_imgview_point, this);

        imgBg = imgPointLayout.findViewById(R.id.imgBg);
        layouPoints = (FrameLayout) imgPointLayout.findViewById(R.id.layouPoints);

        imgBg.setOnScanListener(new ZoomImageView.OnScanListener() {
            @Override
            public void onChanged(float x, float y, float scale) {
                refreshPoints(x, y, scale);
            }
        });

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

    public void setImgBg(int width, int height, String picPath) {
        this.width = width;
        this.height = height;
        Glide.with(mContext).load(picPath).asBitmap().listener(new RequestListener<String, Bitmap>() {
            @Override
            public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
                listener.toSetBitMapInfo(resource.getWidth(), resource.getHeight());
                listener.loadPicSuccess();
                return false;
            }
        }).into(imgBg);
    }

    public void setPoints(List<DevicePointInfo> points) {
        this.points = points;
    }


    private void refreshPoints(float x, float y, float scale) {
        iScale = scale;
        iX = x;
        iY = y;
        NLog.e("refreshPoints", "x=" + x + " y=" + y + " scale=" + scale);
        if (null != points && points.size() > 0) {
            for (DevicePointInfo point : points) {
                setNewXY(point);
            }
        }

    }

    private void setNewXY(DevicePointInfo point) {
        double scaleX = point.getScaleX();
        double scaleY = point.getScaleY();

        View view = point.getPointView();

        double newX = iX + width * scaleX * iScale;
        double newY = iY + height * scaleY * iScale;
        view.setX((float) newX);
        view.setY((float) newY);
        view.setPivotY(0);
        view.setPivotX(0);
        view.setScaleX(iScale);
        view.setScaleY(iScale);

        point.setScreenX((int) newX);
        point.setScreenY((int) newY);
        point.setViewWidth(view.getWidth());
        point.setViewHeight(view.getHeight());
        if (iY != 0) {
            NLog.d("setNewXY-X", "iX=" + iX + " scaleX=" + scaleX + " iScale=" + iScale + " newX=" + newX);
            NLog.d("setNewXY-Y", "iY=" + iY + " scaleY=" + scaleY + " iScale=" + iScale + " newY=" + newY);
        }
    }

    float width;
    float height;

    public void addPoints(List<DevicePointInfo> list) {
        Log.d("onLayout", "addPoints");
        points.clear();
        layouPoints.removeAllViews();
        this.points.addAll(list);

        for (int i = 0; i < points.size(); i++) {
            final DevicePointInfo pointInfo = points.get(i);
            addPoint(pointInfo);
        }
    }


    public void addPoint(final DevicePointInfo pointInfo) {
        double width_scale = pointInfo.getScaleX();
        double height_scale = pointInfo.getScaleY();
        Log.d("addPoint", "width_scale" + width_scale);
        Log.d("addPoint", "height_scale" + height_scale);
        MyPointView view;
        String lineType = pointInfo.getLineType2();

        if (TextUtils.equals("1x", lineType)) {
            view = (MyPointView) LayoutInflater.from(mContext).inflate(R.layout.layout_img_point, this, false);
        } else if (TextUtils.equals("2x", lineType)) {
            view = (MyPointView) LayoutInflater.from(mContext).inflate(R.layout.layout_img_point2, this, false);
        } else if (TextUtils.equals("3x", lineType)) {
            view = (MyPointView) LayoutInflater.from(mContext).inflate(R.layout.layout_img_point3, this, false);
        } else {
            view = (MyPointView) LayoutInflater.from(mContext).inflate(R.layout.layout_img_point, this, false);
        }

        pointInfo.setPointView(view);
        if (!isMultipleModel) {
            view.setPointInfo(pointInfo, false);
        } else {
            view.setPointInfo(pointInfo, selectList.contains(pointInfo));
        }
        layouPoints.addView(view);
        setNewXY(pointInfo);

        setTagTouchEvents(pointInfo);
//        view.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                showDialog(pointInfo);
//            }
//        });
    }


    private void repeatDrawView(DevicePointInfo pointInfo) {
        layouPoints.removeView(pointInfo.getPointView());
        addPoint(pointInfo);
    }

    private void toDealSelectClick(DevicePointInfo pointInfo) {
        if (isMultipleModel) {
            if (selectList.contains(pointInfo)) {
                selectList.remove(pointInfo);
            } else {
                selectList.add(pointInfo);
            }
            pointInfo.getPointView().setPointInfo(pointInfo, selectList.contains(pointInfo));
        } else {
//            for (DevicePointInfo devicePointInfo : selectList) {
//                pointInfo.getPointView().setPointInfo(devicePointInfo,false);
//            }
            selectList.clear();
            selectList.add(pointInfo);
        }
//        if (pointInfo.isSelected()) {
//            pointInfo.setSelected(false);
//        } else {
//            pointInfo.setSelected(true);
//        }
        if (!isMultipleModel) {
            listener.showPointDialog(selectList);
        }
    }

    private void showDialog(DevicePointInfo pointInfo) {
//        if (pointInfo.isSelected()) {
//            pointInfo.setSelected(false);
//        } else {
//            pointInfo.setSelected(true);
//        }
//        pointInfo.getPointView().setPointInfo(pointInfo);
//        listener.selectInfo(getSelectPoints());
//        PointDialog pointDialog = new PointDialog(getContext(), new PointDialog.PointDialogListener() {
//            @Override
//            public void toSetLine(DevicePointInfo pointInfo,int newLineType) {
//                changeLineType(pointInfo,newLineType);
//            }
//
//            @Override
//            public void toUpdate(DevicePointInfo info) {
//                listener.toUpdatePoint(info);
//            }
//
//            @Override
//            public void toDel(DevicePointInfo info) {
//                listener.toDelPoint(info);
//            }
//
//            @Override
//            public void toChangeDirection(DevicePointInfo pointInfo, int direction) {
//                repeatCountPosition(pointInfo, direction);
//            }
//        });
//        pointDialog.display(pointInfo);
    }

    public void delPoint(DevicePointInfo info) {
        layouPoints.removeView(info.getPointView());
        points.remove(info);
    }

    public void delPoint(List<DevicePointInfo> list) {
        for (DevicePointInfo devicePointInfo : list) {
            layouPoints.removeView(devicePointInfo.getPointView());
        }
        selectList.removeAll(list);
        points.removeAll(list);
    }


    @Override
    public void onClick(View view) {
        int pos = (int) view.getTag();
        Toast.makeText(getContext(), "pos : " + pos, Toast.LENGTH_SHORT).show();
    }

    private void setTagTouchEvents(final DevicePointInfo pointInfo) {
        final View tagView = pointInfo.getPointView();
        final GestureDetector mGestureDetector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() {
            int lastX;
            int lastY;
            boolean isMoveing;

            @Override
            public boolean onDown(MotionEvent event) {
                lastX = (int) event.getX();
                lastY = (int) event.getY();
                isMoveing = false;
                return true;
            }

            @Override
            public void onShowPress(MotionEvent e) {
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (!isMoveing && canEdit) {
                    toDealSelectClick(pointInfo);
                }
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent event, float distanceX, float distanceY) {
                NLog.e("setTagTouchEvents", "distanceX=" + distanceX);
                NLog.e("setTagTouchEvents", "distanceY=" + distanceY);

                if (!canEdit) {
                    return false;
                }

                isMoveing = true;
                int x = (int) event.getX();
                int y = (int) event.getY();

                int offsetX = x - lastX;
                int offsetY = y - lastY;

                float newX = tagView.getX() + offsetX;
                float newY = tagView.getY() + offsetY;

                tagView.setX(newX);
                tagView.setY(newY);
                count(pointInfo, newX, newY);
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                isMultipleModel = false;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }

        });

        tagView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        });


    }

    private void count(final DevicePointInfo pointInfo, float newX, float newY) {
//        final View tagView = pointInfo.getPointView();
//        float x = tagView.getX();
//        float y = tagView.getY();

        float scaleX = (newX - iX) / (width * iScale);
        float scaley = (newY - iY) / (height * iScale);
        pointInfo.setScaleX(scaleX);
        pointInfo.setScaleY(scaley);
        pointInfo.setScreenX((int) (width * scaleX));
        pointInfo.setScreenY((int) (height * scaley));

        EntityManager.getInstance().savePointInfo(pointInfo);
    }

    private void repeatCountPosition(final DevicePointInfo pointInfo, int direction) {
        if (pointInfo.getDirection() == direction) {
            return;
        }

        float[] markXY = getMarkXY(pointInfo);
        float markX = markXY[0];
        float markY = markXY[1];

        int vWidth = pointInfo.getPointView().getWidth();
        int vHeight = pointInfo.getPointView().getHeight();

        int textViewwidth = (int) markXY[2];
        int textViewheight = (int) markXY[3];
        int d;
        int deAnger = Math.abs(direction - pointInfo.getDirection());
        if (deAnger != 180) {
            d = Math.abs(textViewwidth - textViewheight);
        } else {
            d = 0;
        }

        float newX = 0;
        float newY = 0;
        if (deAnger != 180) {
            switch (direction) {
                case 0:
                    newX = markX;
                    newY = markY - textViewheight / 2 * iScale;
                    break;
                case 90:
                    newX = markX - textViewwidth / 2 * iScale;
                    newY = markY;
                    break;
                case 180:
                    newX = markX - (vHeight + d) * iScale;
                    newY = markY - textViewheight / 2 * iScale;
                    break;
                case 270:
                    newX = markX - textViewwidth / 2 * iScale;
                    newY = markY - (vWidth - d) * iScale;
                    break;
            }
        } else {
            switch (direction) {
                case 0:
                    newX = markX;
                    newY = markY - (textViewheight) / 2 * iScale;
                    break;
                case 90:
                    newX = markX - textViewwidth / 2 * iScale;
                    newY = markY;
                    break;
                case 180:
                    newX = markX - (vWidth) * iScale;
                    newY = markY - textViewheight / 2 * iScale;
                    break;
                case 270:
                    newX = markX - textViewwidth / 2 * iScale;
                    newY = markY - vHeight * iScale;
                    break;
            }
        }
        pointInfo.setDirection(direction);
        count(pointInfo, newX, newY);
        repeatDrawView(pointInfo);
    }

    private float[] getMarkXY(DevicePointInfo pointInfo) {
        float[] makrXY = new float[4];
        final View tagView = pointInfo.getPointView();
        float x = tagView.getX();
        float y = tagView.getY();


        int vWidth = tagView.getWidth();
        int vHeight = tagView.getHeight();
        View txtView = null;

        float markX = 0;
        float markY = 0;

        switch (pointInfo.getDirection()) {
            case 0:
                txtView = tagView.findViewById(R.id.rightTitleTv);
                markX = x;
                markY = y + vHeight / 2 * iScale;
                break;
            case 90:
                txtView = tagView.findViewById(R.id.downTitleTv);
                markX = x + vWidth / 2 * iScale;
                markY = y;
                break;
            case 180:
                txtView = tagView.findViewById(R.id.leftTitleTv);
                markX = x + vWidth * iScale;
                markY = y + vHeight / 2 * iScale;
                break;
            case 270:
                txtView = tagView.findViewById(R.id.pointTitleTv);
                markX = x + vWidth / 2 * iScale;
                markY = y + vHeight * iScale;
                break;
        }
        NLog.d("getMarkXY", markX + " " + markY);
        makrXY[0] = markX;
        makrXY[1] = markY;
        makrXY[2] = txtView.getWidth();
        makrXY[3] = txtView.getHeight();
        return makrXY;
    }


    private void changeLineType(DevicePointInfo pointInfo, String linetype) {
        if (TextUtils.equals(pointInfo.getLineType2(), linetype)) {
            return;
        }
        int dValue;
        int linedx;
        String oldLineType = pointInfo.getLineType2();
        String oldType = oldLineType.replace("x", "");
        String newType = linetype.replace("x", "");
        linedx = Integer.parseInt(newType) - Integer.parseInt(oldType);
        dValue = linedx * Kits.Dimens.dp2px(25);

        float newX = 0;
        float newY = 0;
        switch (pointInfo.getDirection()) {
            case 0:
                newX = pointInfo.getPointView().getX();
                newY = pointInfo.getPointView().getY();
                break;
            case 90:
                newX = pointInfo.getPointView().getX();
                newY = pointInfo.getPointView().getY();
                break;
            case 180:
                newX = pointInfo.getPointView().getX() - dValue * iScale;
                newY = pointInfo.getPointView().getY();
                break;
            case 270:
                newX = pointInfo.getPointView().getX();
                newY = pointInfo.getPointView().getY() - dValue * iScale;
                break;
        }
        pointInfo.setLineType2(linetype);

        count(pointInfo, newX, newY);
        repeatDrawView(pointInfo);
    }


    public interface ImageLayoutListener {
        void toUpdatePoint(DevicePointInfo pointInfo);

        void toDelPoint(DevicePointInfo pointInfo);

        void toSetBitMapInfo(int width, int height);

        void showPointDialog(List<DevicePointInfo> list);

        void loadPicSuccess();
    }

    public ImageLayout.ImageLayoutListener getListener() {
        return listener;
    }

    public void setListener(ImageLayout.ImageLayoutListener listener) {
        this.listener = listener;
    }

    boolean canEdit;
    boolean doubleSelectModel;

    public void setCanEdit(boolean canEdit) {
        this.canEdit = canEdit;
    }

    public void setMultipleModel(boolean multipleModel) {
        isMultipleModel = multipleModel;
        selectList.clear();
        cancelSelected();
    }

    boolean loadSuccess;

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        int layoutPointsWidth = layouPoints.getWidth();
        if (layoutPointsWidth != 0 && !loadSuccess) {
            loadSuccess = true;
            onLayoutSuccessListener.onLayoutSuccess();
        }
    }

    public void setOnLayoutSuccessListener(ImageLayout.OnLayoutSuccessListener onLayoutSuccessListener) {
        this.onLayoutSuccessListener = onLayoutSuccessListener;
    }

    public interface OnLayoutSuccessListener {
        void onLayoutSuccess();
    }

    public void saveAllPointWH() {
        NLog.d("saveAllPointWH", "saveAllPointWH");
        for (DevicePointInfo point : points) {
            MyPointView pointView = point.getPointView();
            point.setViewWidth(pointView.getWidth());
            point.setViewHeight(pointView.getHeight());
            NLog.d("saveAllPointWH", "point.screanX = " + point.getScreenX());
            NLog.d("saveAllPointWH", "point.screanY = " + point.getScreenY());
        }
        EntityManager.getInstance().savePointInfo(points);
    }

    public void cancelSelected() {
        for (DevicePointInfo point : selectList) {
            point.getPointView().setPointInfo(point, false);
        }
        selectList.clear();
    }

    public void toChangeDirection(int direction) {
        for (DevicePointInfo point : selectList) {
            repeatCountPosition(point, direction);
        }
    }

    public void setBgType(int bgType) {
        for (DevicePointInfo point : selectList) {
            point.setBgType(bgType);
            point.getPointView().setPointInfo(point, isMultipleModel);
        }
    }

    public void toSetLine(String lineType) {
        for (DevicePointInfo point : selectList) {
            changeLineType(point, lineType);
        }
    }

    public List<DevicePointInfo> getSelectPoints() {
        return selectList;
    }

    public void removePoints(List<DevicePointInfo> removePoints) {
        points.removeAll(removePoints);
    }

}
